<?php
/**
 *  TinyMVC - TinyMVCFrontController.class.php file
 * 
 * @author Adrian Wieczorek <adi(at)tinymvc(dot)org>
 * @package TinyMVC
 * @version $Id: TinyMVCFrontController.class.php 3 2007-09-11 12:08:07Z adi3ek $
 * 
 */

/**
 * TinyMVCFrontController class
 * 
 * This is default TinyMVC Framework front controller which handle all requests.
 * It can be instantiated in {@link index.php} bootstrap file, for example:
 * 
 * <code>
 * <?php
 *  $frontController = new TinyMVCFrontController(TinyMVCHttpRequest::getInstance(), new TinyMVCViewRenderer);
 *  
 *  $frontController->doService();
 * ?>
 * </code> 
 * 
 * @package TinyMVC
 */
class TinyMVCFrontController {

	/**
	 * @var TinyMVCActionController
	 */
	protected $actionController;
	/**
	 * @var TinyMVCViewRenderer
	 */
	protected $viewRenderer;
	/**
	 * @var TinyMVCRequest
	 */
	protected $request;
	/**
	 * @var string
	 */
	protected $defaultModuleName;
	/**
	 * @var string
	 */
	protected $defaultActionName;
      
	/**
	 * @param TinyMVCRequest $request Request object
	 * @param TinyMVCViewRenderer $viewRenderer View renderer object
	 * @param string $defaultModuleName Default module name
	 * @param string $defaultActionName Default action name
	 */
	public function __construct(TinyMVCRequest $request, TinyMVCViewRenderer $viewRenderer, $defaultModuleName = 'index', $defaultActionName = 'default') {
		$this->request = $request;
		$this->viewRenderer = $viewRenderer;
	 $this->defaultModuleName = $defaultModuleName;
	 $this->defaultActionName = $defaultActionName;
	}
  
 /**
  * process request
  */
 public function doService() {
  try {				    
   $modelAndView = $this->getActionController()->doAction();

   $this->viewRenderer->render($modelAndView);
  }
  catch(Exception $exception ) {      
   $exception->handleException();      
  }
	}
  
 /**
  * resolves and returns correct action controller for module
  * @return TinyMVCActionController Action controller
  */
 protected function getActionController() {
		if(!$this->request->getParam('mod')) {
	 	$this->request->setParam('mod', $this->defaultModuleName); 
	 }
		$moduleName = strtolower($this->request->getParam('mod'));

 	if(!empty($moduleName)) {
  	if(eregi("^[a-z_]{1,}$", $moduleName)) {
				if(defined('TINYMVC_PROJECT_CONTROLLERS_PATH')) {						
					$actionControllerClassFile = TINYMVC_PROJECT_CONTROLLERS_PATH . '/' . ucfirst($moduleName) . 'ActionController.class.php';						
				}
				else {
					throw new TinyMVCException("Undefined TINYMVC_PROJECT_CONTROLLERS_PATH");							      	      			
				}
			}
	  else {
				throw new TinyMVCException("Invalid characters in module name: $moduleName");							      	
	  }

			if(file_exists($actionControllerClassFile)) {
				require_once($actionControllerClassFile);
				$controllerClassName = ucfirst($moduleName) . 'ActionController';
			}
			else {
				throw new TinyMVCException("ActionController for module: $moduleName - not found.");							
			}
  	
  	$controller = new $controllerClassName(new TinyMVCModelAndView, $this->request, $this->defaultActionName);
  	if($controller instanceof TinyMVCActionController) {
				if(($controller->getModelAndView() == null) || ($controller->getRequest() == null)) {
					throw new TinyMVCException("parent::__construct() has not been called in $controllerClassName::__construct()");
				}
  	}
  	else {
  		throw new TinyMVCException(get_class($controller) . " must extends TinyMVCActionController");
  	}	  
  	return $controller;
		}
		else {
			throw new TinyMVCException("Unknown module name");  			
		} 
 }
}
